#ifndef __MERCKU_UCI_CONFIG_H__
#define __MERCKU_UCI_CONFIG_H__

#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <uci.h>

#include <core/mercku_error.h>

typedef enum
{
    ADD_SECTION = 0,
    ADD_UNNAMED_SECTION,
    DEL_SECTION,
    ADD_OPTION,
    SET_OPTION,
    DEL_OPTION,
    ADD_LIST,
    DEL_LIST
} uci_option_e;

#define MERCKU_UCI_CMD_MAX_LEN (128)
#define MERCKU_UCI_OPTION_MAX_LEN (64)
#define MERCKU_UCI_ARRAY_MAX_LEN (128)
#define MERCKU_UCI_VALUE_MAX_LEN (128)

struct uci_context *mercku_uci_ctx_new(void);
MError * mercku_uci_ctx_set(struct uci_context *ctx, const char *pair);
MError * mercku_uci_ctx_full_set_str(struct uci_context *ctx, const char *package, const char *section, const char *key, const char *value);
MError * mercku_uci_ctx_set_str(struct uci_context *ctx, const char *key, const char *value);
MError * mercku_uci_ctx_full_set_bool(struct uci_context *ctx, const char *package, const char *section, const char *key, bool value);
MError * mercku_uci_ctx_set_bool(struct uci_context *ctx, const char *key, bool value);
MError * mercku_uci_ctx_full_set_i32(struct uci_context *ctx, const char *package, const char *section, const char *key, int32_t value);
MError * mercku_uci_ctx_set_i32(struct uci_context *ctx, const char *key, int32_t value);
MError *mercku_uci_ctx_full_set_u32(struct uci_context *ctx, const char *package, const char *section, const char *key, uint32_t value);
MError *mercku_uci_ctx_set_u32(struct uci_context *ctx, const char *key, uint32_t value);
MError *mercku_uci_ctx_full_set_u64(struct uci_context *ctx, const char *package, const char *section, const char *key, uint64_t value);
MError *mercku_uci_ctx_set_u64(struct uci_context *ctx, const char *key, uint64_t value);
MError * mercku_uci_ctx_cmd(struct uci_context *ctx,
                                  uci_option_e cmd_type, const char *cmd);
MError * mercku_uci_ctx_commit(struct uci_context *ctx,
                                     const char *package);
MError * mercku_uci_ctx_rollback(struct uci_context *ctx,
                                       const char *package);
void mercku_uci_ctx_free(struct uci_context *ctx);
MError * mercku_uci_ctx_get_str(struct uci_context *ctx, const char *key,
                                  char *val);
MError * mercku_uci_ctx_full_get_str(struct uci_context *ctx, const char *package, const char *section, const char *key,
                                  char *val);
MError * mercku_uci_ctx_get_u32(struct uci_context *ctx, const char *key, uint32_t *val);
MError * mercku_uci_ctx_full_get_u32(struct uci_context *ctx, const char *package, const char *section, const char *key,
                                  uint32_t *val);
MError * mercku_uci_ctx_get_u64(struct uci_context *ctx, const char *key, uint64_t *val);
MError * mercku_uci_ctx_full_get_u64(struct uci_context *ctx, const char *package, const char *section, const char *key,
                                  uint64_t *val);
MError * mercku_uci_ctx_get_i32(struct uci_context *ctx, const char *key, uint32_t *val);
MError * mercku_uci_ctx_full_get_i32(struct uci_context *ctx, const char *package, const char *section, const char *key,
                                  uint32_t *val);
MError * mercku_uci_ctx_get_bool(struct uci_context *ctx,
                                       const char *key, bool *val);
MError * mercku_uci_ctx_full_get_bool(struct uci_context *ctx, const char *package, const char *section, const char *key,
                                  bool *val);
MError *
mercku_uci_get(const char *key, char *val);
MError * mercku_uci_ctx_delete_section(struct uci_context *ctx,
                                             const char *cmd);
MError *mercku_uci_ctx_full_delete_section(struct uci_context *ctx, const char *pkg, const char *section);
bool mercku_uci_value_is_true(const char *val);

MError * mercku_uci_get_str(const char *cmd, char *val);
MError * mercku_uci_get_i32(const char *cmd, int32_t *val);
MError * mercku_uci_get_u32(const char *cmd, uint32_t *val);
MError * mercku_uci_get_bool(const char *cmd, bool*val);
MError *mercku_uci_set_bool(const char *cmd, bool val);
MError * mercku_uci_set_str(const char *key, const char *val);
MError * mercku_uci_set_i32(const char *cmd, int32_t val);
MError * mercku_uci_set_u32(const char *cmd, uint32_t val);

int32_t mercku_uci_array_find(const char *cfg, const char *key,
                              const char *val);
MError * mercku_uci_array_update(const char *cfg, int32_t idx,
                                       const char *key, const char *val);
MError * mercku_uci_array_get(const char *cfg, int32_t idx,
                                    const char *key, char *val);

int32_t mercku_uci_array_find_int(const char *cfg, const char *key,
                                  int32_t val);
MError * mercku_uci_array_update_int(const char *cfg, int32_t idx,
                                           const char *key, int32_t val);
MError * mercku_uci_array_get_int(const char *cfg, int32_t idx,
                                        const char *key, int32_t *val);
MError *mercku_uci_ctx_add_named_section(struct uci_context *ctx, const char *pkg, const char *section, const char *sec_type);

#endif //__MERCKU_UCI_CONFIG_H__
